﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.VisualStudio.Modeling.Validation;
using System.Collections;

namespace nHydrate.Dsl
{
	[ValidationState(ValidationState.Enabled)]
	partial class Composite
	{
		[ValidationMethod(ValidationCategories.Open | ValidationCategories.Save | ValidationCategories.Menu | ValidationCategories.Custom | ValidationCategories.Load)]
		public void Validate(ValidationContext context)
		{
			var timer = nHydrate.Dsl.Custom.DebugHelper.StartTimer();
			try
			{
				if (!this.IsGenerated) return;

				#region Check valid name
				if (!ValidationHelper.ValidDatabaseIdenitifer(this.DatabaseName))
					context.LogError(string.Format(ValidationHelper.ErrorTextInvalidIdentifierComposite, this.Name, this.Entity.Name), string.Empty, this);
				else if (!ValidationHelper.ValidCodeIdentifier(this.PascalName))
					context.LogError(string.Format(ValidationHelper.ErrorTextInvalidIdentifierComposite, this.Name, this.Entity.Name), string.Empty, this);
				#endregion

				#region Table Component must have PK for parent table
				int pkCount = 0;
				foreach (var field in this.GetFields())
				{
					if (this.Entity.PrimaryKeyFields.Contains(field))
						pkCount++;
				}

				if (pkCount != this.Entity.PrimaryKeyFields.Count)
				{
					context.LogError(String.Format(ValidationHelper.ErrorTextComponentMustHaveTablePK, this.Name), string.Empty, this);
				}
				#endregion

				#region Check valid name
				if (!ValidationHelper.ValidCodeIdentifier(this.PascalName))
					context.LogError(string.Format(ValidationHelper.ErrorTextInvalidIdentifierComposite, this.Name, this.Entity.Name), string.Empty, this);
				#endregion

				#region Check that object does not have same name as project

				if (this.PascalName == this.Entity.nHydrateModel.ProjectName)
				{
					context.LogError(string.Format(ValidationHelper.ErrorTextComponentProjectSameName, this.Name), string.Empty, this);
				}

				#endregion

				#region Check for classes that will confict with generated classes

				var classExtensions = new List<string>();
				classExtensions.Add("collection");
				classExtensions.Add("enumerator");
				classExtensions.Add("query");
				//classExtensions.Add("search");
				classExtensions.Add("pagingfielditem");
				classExtensions.Add("paging");
				classExtensions.Add("primarykey");
				classExtensions.Add("selectall");
				classExtensions.Add("pagedselect");
				classExtensions.Add("selectbypks");
				classExtensions.Add("selectbycreateddaterange");
				classExtensions.Add("selectbymodifieddaterange");
				classExtensions.Add("selectbysearch");
				classExtensions.Add("beforechangeeventargs");
				classExtensions.Add("afterchangeeventargs");

				foreach (var ending in classExtensions)
				{
					if (this.PascalName.ToLower().EndsWith(ending))
					{
						context.LogError(string.Format(ValidationHelper.ErrorTextNameConfictsWithGeneratedCode, this.Name), string.Empty, this);
					}
				}

				#endregion
			}
			catch (Exception ex)
			{
				throw;
			}
			finally
			{
				nHydrate.Dsl.Custom.DebugHelper.StopTimer(timer, "Composite Validate - Main");
			}

		}

		[ValidationMethod(ValidationCategories.Open | ValidationCategories.Save | ValidationCategories.Menu | ValidationCategories.Custom | ValidationCategories.Load)]
		public void ValidateFields(ValidationContext context)
		{
			var timer = nHydrate.Dsl.Custom.DebugHelper.StartTimer();
			try
			{
				if (!this.IsGenerated) return;
				var columnList = this.GetFields().Where(x => x.IsGenerated).ToList();

				if (columnList.Count == 0)
					context.LogError(string.Format(ValidationHelper.ErrorTextTableComponentNoColumns, this.Name), string.Empty, this);

				#region Check for duplicate names
				var nameList = new HashSet<string>();
				foreach (var column in columnList)
				{
					var name = column.PascalName.ToLower();
					if (nameList.Contains(name))
						context.LogError(string.Format(ValidationHelper.ErrorTextDuplicateName, column.Name), string.Empty, this);
					else
						nameList.Add(name);
				}
				#endregion

			}
			catch (Exception ex)
			{
				throw;
			}
			finally
			{
				nHydrate.Dsl.Custom.DebugHelper.StopTimer(timer, "Composite Validate - Fields");
			}

		}

	}
}